
/**
 *     P3.java
 *
 *       Extends LinkUtilPlayer with simple animation of impulses on links.
 */

import SSF.Net.*;
import SSF.OS.NetFlow.BytesUtil;
import com.renesys.raceway.views.*;
import java.awt.Color;
import java.util.*;

public class P3 extends LinkUtilPlayer {

    int MAXPULSE = 20; // 20 pulses per wire

    //    HashMap pulseTrains = new HashMap();
    ArrayList[] pulseTrains;

    class Sample {
	Object pulse;
	Color color;
	public Sample(Color c) {
	    color = c;
	}
    }

    public void play(Stream.Record r) {
	int typeid   = r.type_code;
	int srcid    = r.source_code;
	double time  = r.timestamp;
	byte[] buf   = r.bytes;
	int bindex   = r.offset;
	int length   = r.length;
	
        if (!stream.getRecordTypeString(typeid).equals
	    ("SSF.Net.QueueRecord_2")) 
	    return; // let someone else render it
        
	int sumct = BytesUtil.bytesToInt(buf,bindex+0);
	int sumdrop = BytesUtil.bytesToInt(buf,bindex+4);
	int ct = BytesUtil.bytesToInt(buf,bindex+8);
	int drop = BytesUtil.bytesToInt(buf,bindex+12);
	
	String src_nhi = stream.getRecordSourceString(srcid);

	Raceway.VisibleLink L = stream.raceway().getVisibleLink(src_nhi);

	if (null != L) {

	    if (null==pulseTrains) 
		pulseTrains = new ArrayList[2*numHosts];
	    
	    ArrayList pulses = pulseTrains[srcid];
	    if (null==pulses) pulses = pulseTrains[srcid] = new ArrayList();

	    Color c = Color.gray;
	    if (ct>1000) 
		c = Color.red;
	    else if (ct>100) 
		c = Color.orange;
	    else if (ct>10) 
		c = Color.yellow;
	    else if (ct>0) 
		c = Color.green;

	    // 1. Cancel the last pulse in the train..

	    Sample save = null;
	    if (pulses.size()>MAXPULSE) {
		save = (Sample)(pulses.get(pulses.size()-1));
		L.pulse(save.pulse,0.,0.,0,0,0,null);
		pulses.remove(pulses.size()-1);
	    }

	    // 2. Prepend a new pulse to the head of the train ..

	    Sample newSample = (null==save?new Sample(c):save);
	    newSample.color = c;
	    newSample.pulse = L.pulse(newSample.pulse,0.,0.8/MAXPULSE,
				      2,4,L.LEFT,c);
	    pulses.add(0,newSample);

	    // 3. Move the rest of the pulses in the train ..

	    for (int n=1; n<pulses.size(); n++) {
		Sample S = (Sample)pulses.get(n);
		L.pulse(S.pulse,
			(n*1.)/MAXPULSE,       // start
			((n+0.8)*1.)/MAXPULSE,   // stop
			2,4,L.LEFT,
			S.color);
	    }

	    L.refresh(); // TEST repainting only impulses
	} 
    }
}

